package client;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;

/**
 * Class MatmBcbsApp assigns actions to screens
 * 
 * @author XA9
 * 
 */

public class MatmBcbsApp {

	private ScreenMATM screenMatm;
	private boolean userAuthenticated;
	private int currentAccountNumber;
	private String currentLoginId;
	private MATM_Client client;

	/**
	 * 
	 * @param port
	 * @param hostname
	 */

	public MatmBcbsApp(int port, String hostname) {
		userAuthenticated = true;
		currentAccountNumber = 0;

		try {
			this.client = new MATM_Client(hostname, port);
		} catch (IOException e) {
			e.printStackTrace();
		}

		screenMatm = new ScreenMATM();
		screenMatm.getScreen_Login().addActionListener(
				new Screen_LoginActionListener(this));
		screenMatm.getScreen_Menu().addActionListener(
				new Screen_MenuActionListener(this));
		screenMatm.getScreen_Balance().addActionListener(
				new Screen_BalanceActionListener(this));
		screenMatm.getScreen_Deposit().addActionListener(
				new Screen_DepositActionListener(this));
		screenMatm.getScreen_SendBtc().addActionListener(
				new Screen_SendBtcActionListener(this));

	}

	/**
	 * 
	 */
	public void run() {
		screenMatm.Show(ScreenMATM.SCREENLOGIN);
		screenMatm.setVisible(true);
	}

	/**
	 * Customer login screen which grants access to the screen menu if user is
	 * authenticated
	 * 
	 */

	private class Screen_LoginActionListener implements ActionListener {
		private MatmBcbsApp matmBcbsApp;

		public Screen_LoginActionListener(MatmBcbsApp instance) {
			this.matmBcbsApp = instance;
		}

		public void actionPerformed(ActionEvent e) {

			/**
			 * Gets send to the customer menu or print out
			 * "wrong login or password"
			 */

			if (e.getSource() == screenMatm.getScreen_Login().getBtnLogin()) {

				try {
					matmBcbsApp.authenticateUser();

				} catch (IOException e1) {
					e1.printStackTrace();
				}

			}

		}

	}

	/**
	 * Customer menu actionListener choose between screens based on user
	 * selection
	 * 
	 */
	private class Screen_MenuActionListener implements ActionListener {
		private MatmBcbsApp matmBcbsApp;

		public Screen_MenuActionListener(MatmBcbsApp instance) {
			this.matmBcbsApp = instance;
		}

		/**
		 * Sends you to the view balance screen
		 */

		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == screenMatm.getScreen_Menu().getBtnBalance()) {
				screenMatm.getScreen_Balance().setTfBtcBalance(
						this.matmBcbsApp.currentAccountNumber);
				screenMatm.getScreen_Balance().setTfBtcBalanceDkk(
						this.matmBcbsApp.currentAccountNumber);

				try {
					double balanceDB = matmBcbsApp.client
							.getBalance(currentLoginId);
					double balanceDBDkk = matmBcbsApp.client
							.getBalanceDkk(currentLoginId);
					screenMatm.getScreen_Balance().setTfBtcBalance(balanceDB);
					screenMatm.getScreen_Balance().setTfBtcBalanceDkk(
							balanceDBDkk);

					screenMatm.Show(ScreenMATM.SCREENBALANCE);
				} catch (NumberFormatException | IOException e1) {
					e1.printStackTrace();
				}
			}

			/**
			 * Sends you to the deposit funds screen
			 */
			else if (e.getSource() == screenMatm.getScreen_Menu()
					.getBtnDeposit()) {
				screenMatm.Show(ScreenMATM.DEPOSITFUNDS);
			}

			/**
			 * Sends you to the deposit funds screen
			 */
			else if (e.getSource() == screenMatm.getScreen_Menu()
					.getBtnSendBtc()) {
				screenMatm.Show(ScreenMATM.SENDBTC);
			}
			/**
			 * When log out return to the customer login screen
			 */

			else if (e.getSource() == screenMatm.getScreen_Menu()
					.getBtnLogOut()) {
				this.matmBcbsApp.logOut();

				screenMatm.Show(ScreenMATM.SCREENLOGIN);
				screenMatm.getScreen_Login().clearFields();

			}
		}
	}

	private class Screen_BalanceActionListener implements ActionListener {

		private MatmBcbsApp matmBcbsApp;

		public Screen_BalanceActionListener(MatmBcbsApp instance) {
			this.matmBcbsApp = instance;
		}

		/**
		 * Returns to main menu from Screen_Balance
		 */
		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == screenMatm.getScreen_Balance().getBtnReturn()) {

				screenMatm.Show(ScreenMATM.SCREENMENU);

			}
		}
	}

	private class Screen_DepositActionListener implements ActionListener {

		private MatmBcbsApp matmBcbsApp;

		public Screen_DepositActionListener(MatmBcbsApp instance) {
			this.matmBcbsApp = instance;
		}

		/**
		 * Returns to main menu from Screen_Deposit
		 */
		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == screenMatm.getScreen_Deposit().getBtnReturn()) {

				screenMatm.Show(ScreenMATM.SCREENMENU);
				screenMatm.getScreen_Deposit().clearFields();

			}

			else if (e.getSource() == screenMatm.getScreen_Deposit()
					.getBtnDeposit()) {

				double money = screenMatm.getScreen_Deposit()
						.getDepositAmount();
				if (money >= 0) {

					System.out.println(money);

					try {
						matmBcbsApp.client.depositDkk(currentLoginId, money);
					} catch (IOException e1) {
						e1.printStackTrace();
					}
				} else {
					screenMatm
							.showMessage("You can not deposit a negativ amount");
				}

				screenMatm
						.showMessage("You've succesfully deposited the amount!");
				screenMatm.Show(ScreenMATM.SCREENMENU);
				screenMatm.getScreen_Deposit().clearFields();

			}
		}
	}

	private class Screen_SendBtcActionListener implements ActionListener {

		private MatmBcbsApp matmBcbsApp;

		public Screen_SendBtcActionListener(MatmBcbsApp instance) {
			this.matmBcbsApp = instance;
		}

		/**
		 * Performs method checkAmount when user pushes send-button
		 */
		public void actionPerformed(ActionEvent e) {
			if (e.getSource() == screenMatm.getScreen_SendBtc().getBtnSendBtc()) {

				try {
					checkAmount();

				} catch (NumberFormatException | IOException e1) {
					e1.printStackTrace();
				}

			}
			/**
			 * Returns to main menu from Screen_SendBtc
			 */
			else if (e.getSource() == screenMatm.getScreen_SendBtc()
					.getBtnReturn()) {

				screenMatm.Show(ScreenMATM.SCREENMENU);
				screenMatm.getScreen_SendBtc().clearFields();

			}
		}
	}

	/**
	 * Gets user input logId and password and checks against database
	 * if the user is authenticated
	 * 
	 * @throws IOException
	 */
	public void authenticateUser() throws IOException {
		String loginId;
		String password;

		loginId = screenMatm.getScreen_Login().getTfLoginId();
		password = screenMatm.getScreen_Login().getPfPassword();

		boolean isAuthed = this.client.auth(loginId, password);

		if (isAuthed) {
			currentLoginId = loginId;
			screenMatm.Show(ScreenMATM.SCREENMENU);

		} else {
			screenMatm.showMessage("Invalid username or password!");
			screenMatm.Show(ScreenMATM.SCREENLOGIN);
			screenMatm.getScreen_Login().clearFields();
		}
	}

	/**
	 * 
	 * Returns isAuthed
	 * 
	 * @return boolean userAuthenticated
	 * 
	 */

	public boolean isAuthed() {
		return this.userAuthenticated;
	}
	
	/**
	 * Gets user input e-mail and amount, then sends
	 * amount to the written e-mail and subtracts amount on the current account
	 * 
	 * @param mailReceiver
	 * @param amountReceiver
	 * @param currentAmount
	 * @throws NumberFormatException
	 * @throws IOException
	 */

	public void checkAmount() throws NumberFormatException, IOException {

		String mailReceiver = screenMatm.getScreen_SendBtc()
				.getCbsmailReceive();
		double amountReceiver = screenMatm.getScreen_SendBtc().getAmountBtc();

		double currentAmount = this.client.getBalance(currentLoginId);
		if (amountReceiver > 0) {
			if (amountReceiver <= currentAmount) {

				this.client.sendBitCoins(currentLoginId, amountReceiver);
				this.client.depositBtc(mailReceiver, amountReceiver);

				screenMatm.showMessage("Your Bitcoins was succesfully sent!");
				screenMatm.getScreen_SendBtc().clearFields();
				screenMatm.Show(ScreenMATM.SCREENMENU);

			} else {

				screenMatm.showMessage("You do not have enough money"
						+ "\non your account for the chosen transaction");

				screenMatm.getScreen_SendBtc().clearFields();
				screenMatm.Show(ScreenMATM.SCREENMENU);
			}
		} else {
			screenMatm.showMessage("You can not send a negativ amount");
			screenMatm.getScreen_SendBtc().clearFields();
		}

	}

	/**
	 * Returns authenticated user
	 * 
	 * @return userAuthenticated
	 */
	public void logOut() {
		this.userAuthenticated = false;

	}
}